﻿using System;
using System.Collections.Generic;
using System.Data;
using UnityEngine;

namespace com.susi.util {
    public static class ArrayUtil {
        /// <summary>
        /// 将元素加到空位上（如已满则resize）
        /// </summary>
        public static void Add<T>(ref T[] array, T item) where T : class
        {
            if (array == null) throw new ArgumentNullException(nameof(array));
            for (var p = 0; p < array.Length; p++)
            {
                if (array[p] == null)
                {
                    array[p] = item;
                    return;
                }
            }
            Array.Resize(ref array, array.Length + 1);
            array[array.Length - 1] = item;
        }
        
        /// <summary>
        /// 将元素加到空位上（如已满则resize）
        /// </summary>
        public static void Add<T>(ref T[] array, T item, Func<T,bool> IsCanBeReplace) 
        {
            if (array == null) throw new ArgumentNullException(nameof(array));
            if(IsCanBeReplace==null)throw new ArgumentNullException(nameof(IsCanBeReplace));
            for (var p = 0; p < array.Length; p++)
            {
                if (IsCanBeReplace(array[p])) {
                    array[p] = item;
                    return;
                }
            }
            Array.Resize(ref array, array.Length + 1);
            array[array.Length - 1] = item;
        }
        
        /// <summary>
        /// resize并添加到最后一位，会创建array
        /// </summary>
        [Obsolete("chaos about new")]
        public static void AddToNew<T>(ref T[] array, T item)
        {
            if (array == null)
            {
                array = new T[] {item};
                return;
            }
            Array.Resize(ref array, array.Length + 1);
            array[array.Length - 1] = item;
        }

        /// <summary>
        /// 待优化
        /// </summary>
        public static void RemoveAndResize<T>(ref T[] ary, T item)where T : class
        {
            List<T> lst = new List<T>(ary);
            lst.Remove(item);
            ary = lst.ToArray();
        }

        /// <summary>
        /// 如果数组已满则插入失败。IsCanBeReplace为true的元素视作空元素会被替换
        /// </summary>
        public static bool Insert<T>(ref T[] array, int idx, T item, Func<T, bool> IsCanBeReplace)
        {
#if DEBUG
            if (idx >= array.Length) throw new ArgumentOutOfRangeException(nameof(idx));
            if (array == null) throw new NoNullAllowedException(nameof(array));
            if (IsCanBeReplace == null) throw new NoNullAllowedException(nameof(IsCanBeReplace));
#endif
            if (IsCanBeReplace(array[idx])) {
                array[idx] = item;
                return true;
            }
            else {
                var p   = idx;
                var len = array.Length;
                while (p<len && IsCanBeReplace(array[p])==false) p++;
                if (p == len) return false; //array is full
                for (; p > idx; p--) array[p] = array[p - 1];
                array[idx] = item;
                return true;
            }
        }
        
        /// <summary>
        /// 如果数组已满则插入失败。
        /// </summary>
        public static bool Insert<T>(ref T[] array, int idx, T item) where T:class
        {
#if DEBUG
            if (idx >= array.Length) throw new ArgumentOutOfRangeException(nameof(idx));
            if (array == null) throw new NoNullAllowedException(nameof(array));
#endif
            if (array[idx] == null) {
                array[idx] = item;
                return true;
            }
            else {
                var p   = idx;
                var len = array.Length;
                while (p<len && array[p]!=null) p++;
                if (p == len) return false; //array is full
                for (; p > idx; p--) array[p] = array[p - 1];
                array[idx] = item;
                return true;
            }
        }
        
        
    }
}